﻿using System.Collections.Generic;



namespace ScriptEase.Shell.NLog
{
  /// <summary>
  /// </summary>
  public static class NLogReceiver
  {
    /// <summary>
    /// </summary>
    /// <param name="timeStamp">The time stamp.</param>
    /// <param name="level">The level.</param>
    /// <param name="message">The message.</param>
    /// <param name="thread">The thread.</param>
    public delegate void MessageReceiver(string timeStamp, string level, string message, string thread);


    //
    // Private list to manage message receivers
    // 
    private static readonly object _listLock = new object();
    private static readonly List<MessageReceiver> _messageReceiver = new List<MessageReceiver>();


    /// <summary>
    /// Message listeners can subscribe to receive NLog messages.
    /// </summary>
    /// <param name="messageReceiver"></param>
    public static void Subscribe(MessageReceiver messageReceiver)
    {
      lock (_listLock)
      {
        _messageReceiver.Add(messageReceiver);
      }
    }


    /// <summary>
    /// Message listeners can unsubscribe to receive NLog messages.
    /// </summary>
    /// <param name="messageReceiver"></param>
    public static void UnSubscribe(MessageReceiver messageReceiver)
    {
      lock (_listLock)
      {
        _messageReceiver.Remove(messageReceiver);
      }
    }



    /// <summary>
    /// When configured <see cref="NLog"/> messages will go to here!
    /// </summary>
    /// <param name="timeStamp">The time stamp.</param>
    /// <param name="level">The level.</param>
    /// <param name="message">The message.</param>
    /// <param name="thread">The thread.</param>
    /// <example>
    /// How to configure NLog:
    ///   <code>
    /// &lt;target name="ApplicationLogWindow"
    /// xsi:type="MethodCall"
    /// className="CrmWebServices.UI.NLogReceiver, CrmWebServices.UI"
    ///   <b>methodName="MessageReceiverTarget"&gt;</b>
    /// &lt;parameter layout="${level}" /&gt;
    /// &lt;parameter layout="${message}" /&gt;
    /// &lt;/target&gt;
    ///   </code>
    ///   <br/>
    /// A form can than subscribe and receive the for messages:
    ///   <code>
    /// NLogReceiver.Subscribe(new NLogReceiver.MessageReceiver(nLogMessageReceiver));
    /// void nLogMessageReceiver(string level, string message)
    /// {
    /// if (this.textMessage.InvokeRequired)
    /// {
    /// MethodInvoker del = () =&gt; nLogMessageReceiver(level, message);
    /// this.Invoke(del);
    /// return;
    /// }
    /// this.textMessage.Text += message;
    /// }
    ///   </code>
    ///   </example>
    /// <remarks>
    /// This method must be configured as a <c>MethodCall</c> target in the NLOG configuration.
    /// </remarks>
    public static void MessageReceiverTarget(string timeStamp, string level, string message, string thread)
    {
      lock (_listLock)
      {
        foreach (MessageReceiver messageReceiver in _messageReceiver)
        {
          messageReceiver.BeginInvoke(timeStamp, level, message, thread, null, null);
        }
      }
    }
  }
}